//
//  BaseBaiduMapHandler.swift
//  ANOASTORE
//
//  Created by hudan on 2025/11/24.
//  Copyright © 2025 zwb. All rights reserved.
//

import UIKit

/// 百度地图的 Helper
final class bMapHelper: NSObject {
    static let shared = bMapHelper()
    private override init() {}
    
    var compositeManager: BMKMapManager!
    
    var initable = false

    func initMap() {
        if !initable {
            var baiduMapKey = AppKey.baiduMapKey
            
            let iosA = USERINFO.mapKey.filter{ $0.c_platform == "ios" }
            if iosA.count > 0 {
                
                KSLog("初始化高德x动态--\(iosA.first!.c_map_key.unwrap)")
                
                baiduMapKey = iosA.first!.c_map_key.unwrap
                
            } else {
                KSLog("初始化高德x固定--\(AppKey.baiduMapKey)")
                
            }
            
            BNaviService.setAgreePrivacy(true)
            
            BMKLocationAuth.sharedInstance()?.checkPermision(withKey: baiduMapKey, authDelegate: self)
            // ‼️重要：设置用户是否同意定位SDK隐私协议
            BMKLocationAuth.sharedInstance()?.setAgreePrivacy(true)
            
            // ‼️重要：设置用户是否同意SDK隐私协议
            BMKMapManager.setAgreePrivacy(true)

            //要使用百度地图，请先启动BMKMapManager
            compositeManager = BMKMapManager()
            /**
             百度地图SDK所有API均支持百度坐标（BD09）和国测局坐标（GCJ02），用此方法设置您使用的坐标类型.
             默认是BD09（BMK_COORDTYPE_BD09LL）坐标.
             如果需要使用GCJ02坐标，需要设置CoordinateType为：BMK_COORDTYPE_COMMON.
             */
            if BMKMapManager.setCoordinateTypeUsedInBaiduMapSDK(BMK_COORD_TYPE.COORDTYPE_BD09LL) {
                NSLog("经纬度类型设置成功")
            } else {
                NSLog("经纬度类型设置失败")
            }
            //启动引擎并设置AK并设置delegate
//            if !(compositeManager!.start("UL1BdzE56YtxC7NbwgSqDZSNzYb8lOy9", generalDelegate: self)) {
            if !(compositeManager!.start(baiduMapKey, generalDelegate: self)) {
                NSLog("启动引擎失败")
            } else {
                initable = true
            }
        }
    }
}

extension bMapHelper: BMKGeneralDelegate {
    // 获取授权错误
    func onGetPermissionState(_ iError: Int32) {
        if 0 == iError {
            KSLog("授权成功")
        } else {
            NSLog("授权失败：%d", iError)
        }
    }
    
    func onGetNetworkState(_ iError: Int32) {
        if 0 == iError {
            KSLog("联网成功")
        } else {
            NSLog("联网失败：%d", iError)
        }
    }
}

extension bMapHelper: BMKLocationAuthDelegate {
    func onCheckPermissionState(_ iError: BMKLocationAuthErrorCode) {
        KSLog("onCheckPermissionState = \(iError)")
    }
}


final class BaseBaiduMapHandler: BaseMapManager, BMKMapViewDelegate {
        
    var update: ((CLLocationCoordinate2D, String) -> Void)?
    
    //初始化BMKUserLocation的实例
    var userLocation: BMKUserLocation = BMKUserLocation()
    
    lazy var locationManager: BMKLocationManager = {
        //初始化BMKLocationManager的实例
        let manager = BMKLocationManager()
        //设置定位管理类实例的代理
        manager.delegate = self
        //设定定位坐标系类型，默认为 BMKLocationCoordinateTypeGCJ02
        manager.coordinateType = BMKLocationCoordinateType.BMK09LL
        //设定定位精度，默认为 kCLLocationAccuracyBest
        manager.desiredAccuracy = kCLLocationAccuracyBest
        //设定定位类型，默认为 CLActivityTypeAutomotiveNavigation
        manager.activityType = CLActivityType.automotiveNavigation
        //指定定位是否会被系统自动暂停，默认为NO
        manager.pausesLocationUpdatesAutomatically = false
        /**
         是否允许后台定位，默认为NO。只在iOS 9.0及之后起作用。
         设置为YES的时候必须保证 Background Modes 中的 Location updates 处于选中状态，否则会抛出异常。
         由于iOS系统限制，需要在定位未开始之前或定位停止之后，修改该属性的值才会有效果。
         */
        manager.allowsBackgroundLocationUpdates = false
        /**
         指定单次定位超时时间,默认为10s，最小值是2s。注意单次定位请求前设置。
         注意: 单次定位超时时间从确定了定位权限(非kCLAuthorizationStatusNotDetermined状态)
         后开始计算。
         */
        manager.locationTimeout = 10
        return manager
    }()
    
    lazy var mapView: BMKMapView = {
        let mapView = BMKMapView(frame: frame)
        //设置mapView的代理
        mapView.delegate = self
        return mapView
    }()
    
    var frame: CGRect = .zero
    
    var isLocationOnce = false
    var locationTimes = 0
        
    func getMapView(zoomLevel: Float = 17, showsUserLocation: Bool = false, tipOffset: CGFloat = 0, frame: CGRect = .zero) -> UIView {
        if LocationTool.shared.getPermission() {
            

            self.frame = frame == .zero ? CGRect(origin: .zero, size: CGSize(width: KS_SCREEN_WIDTH, height: 200)) : frame

            mapView.userTrackingMode = BMKUserTrackingModeHeading
            mapView.showsUserLocation = showsUserLocation
            mapView.zoomLevel = zoomLevel
            
            return mapView
    
        } else {
            let tipV = UIView()
            addTipButton(superV: tipV, tipOffset)
            return tipV
        }
    }
    
    func startLocation() {
        isLocationOnce = false
        locationManager.startUpdatingHeading()
        locationManager.startUpdatingLocation()
        mapView.showsUserLocation = true
    }
    
    // 定位一次
    func locationOnce(complete: @escaping (() -> Void)) {
        locationManager.requestLocation(withReGeocode: false, withNetworkState: false) { location, netState, err in
            complete()
        }
    }
    
    func stopLocation() {
        locationManager.stopUpdatingHeading()
        locationManager.startUpdatingLocation()
        //不显示定位图层
        mapView.showsUserLocation = false
    }
    
    func setCenterCoordinate(_ coor: CLLocationCoordinate2D) {
        mapView.centerCoordinate = coor
    }
    
    func addOverlays(_ overlays: [any BMKOverlay]) {
        mapView.addOverlays(overlays)
    }
    
    func removeOverlays() {
        if let anOverlays = self.mapView.overlays {
            self.mapView.removeOverlays(anOverlays)
        }
    }
    
    func add(_ overlays: BMKPolyline) {
        self.mapView.add(overlays)
    }
    
    func mapIsScrollEnabled(flag: Bool) {
        self.mapView.isScrollEnabled = flag
    }
 
    func removeAnnotations() {
        if let anAnnotations = self.mapView.annotations {
            self.mapView.removeAnnotations(anAnnotations)
        }
    }
    
    func removeAnnotation(_ annotation: BMKAnnotation) {
        self.mapView.removeAnnotation(annotation)
    }
    
    func removeAnnotations(_ annotations: [BMKAnnotation]) {
        self.mapView.removeAnnotations(annotations)
    }
    
    func addAnnotations(_ annotations:[any BMKAnnotation]) {
        mapView.addAnnotations(annotations)
    }
    
    func addAnnotation(_ annotation: BMKPointAnnotation) {
        mapView.addAnnotation(annotation)
    }
    
    // 地图适应所有的点显示
    func mapViewFitForCoordinates(_ points: [CLLocationCoordinate2D]) {
        var minLat: Double = 90.0
        var maxLat: Double = -90.0
        var minLon: Double = 180.0
        var maxLon: Double = -180.0
        
        for item in points {
            minLat = fmin(minLat, item.latitude)
            maxLat = fmax(maxLat, item.latitude)
            minLon = fmin(minLon, item.longitude)
            maxLon = fmax(maxLon, item.longitude)
        }
        
        let center = CLLocationCoordinate2D(latitude: (minLat + maxLat) * 0.5, longitude: (minLon + maxLon) * 0.5)
        
        var span = BMKCoordinateSpan()
        span.latitudeDelta = (maxLat - minLat) + 0.01
        span.longitudeDelta = (maxLon - minLon) + 0.01
        var region = BMKCoordinateRegion()
        region.center = center
        region.span = span
        mapView.setRegion(region, animated: true)
    }
    
    //根据polyline设置地图范围
    func mapViewFitPolyLine(_ polyline: BMKPolyline!) {
        if polyline.pointCount < 1 {
            return
        }
        
        let pt = polyline.points[0]
        var leftTopX = pt.x
        var leftTopY = pt.y
        var rightBottomX = pt.x
        var rightBottomY = pt.y
        
        for i in 1..<polyline.pointCount {
            let pt = polyline.points[Int(i)]
            leftTopX = pt.x < leftTopX ? pt.x : leftTopX
            leftTopY = pt.y < leftTopY ? pt.y : leftTopY
            rightBottomX = pt.x > rightBottomX ? pt.x : rightBottomX
            rightBottomY = pt.y > rightBottomY ? pt.y : rightBottomY
        }
        
        let rect = BMKMapRectMake(leftTopX - (rightBottomX - leftTopX) / 6, leftTopY - (rightBottomY - leftTopY) / 6, (rightBottomX - leftTopX) / 2 * 3, (rightBottomY - leftTopY) / 2 * 3)
        mapView.visibleMapRect = rect
    }
}

extension BaseBaiduMapHandler: BMKLocationManagerDelegate {
    func bmkLocationManager(_ manager: BMKLocationManager, didUpdate heading: CLHeading?) {
        NSLog("用户方向更新")
        userLocation.heading = heading
        mapView.updateLocationData(userLocation)
    }
    
    /**
     @brief 连续定位回调函数
     @param manager 定位 BMKLocationManager 类
     @param location 定位结果，参考BMKLocation
     @param error 错误信息。
     */
    func bmkLocationManager(_ manager: BMKLocationManager, didUpdate location: BMKLocation?, orError error: Error?) {
        if let _ = error?.localizedDescription {
            NSLog("locError:%@;", (error?.localizedDescription)!)
        }
        userLocation.location = location?.location
        //实现该方法，否则定位图标不出现
        mapView.updateLocationData(userLocation)
        
        if update != nil && location?.location != nil {
            var dealLocation = location?.location
            if isBaiduMapPlatform() {
                let trans = BMKCoordTrans(dealLocation!.coordinate, BMK_COORD_TYPE.COORDTYPE_BD09LL, BMK_COORD_TYPE.COORDTYPE_COMMON)
                dealLocation = CLLocation(latitude: trans.latitude, longitude: trans.longitude)
            }

            
            let geocoder = CLGeocoder()
            geocoder.reverseGeocodeLocation(dealLocation!) { [weak self] (placemarks, error) in
                if error.isSome {
                   
                }
                
                if let placemark = placemarks?.last {
                    
                    let address = "\(placemark.administrativeArea.unwrap)\(placemark.locality.unwrap)\(placemark.subLocality.unwrap)\(placemark.name.unwrap)"
                    
                    self?.update?(dealLocation!.coordinate, address)
                } else {
                    self?.update?(dealLocation!.coordinate, "")
                }
            }
        }
    }
}




